home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / interapplication comm / 7edit / source / svaesetdata.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  22.0 KB  |  813 lines

  1. /*
  2.     File:        SVAESetData.c
  3.  
  4.     Contains:    
  5.  
  6.     Written by: Original version by Jon Lansdell and Nigel Humphreys.
  7.                 3.1 updates by Greg Sutton.
  8.  
  9.     Copyright:    Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/20/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22.  
  23. */
  24.  
  25. #include "SVAESetData.h"
  26.  
  27. #include "SVEditWindow.h"
  28. #include "SVEditGlobals.h"
  29. #include "SVEditAEUtils.h"
  30. #include "SVAETextUtils.h"
  31. #include "SVAppleEvents.h"
  32.  
  33. #include "SVAESelect.h"
  34. #include "SVAECreate.h"
  35.  
  36. #include <string.h>
  37. #include <TextUtils.h>
  38. #include <DriverServices.h>
  39.  
  40.  
  41. // --------------------------------------------------------------------------
  42. //    Name:             DoSetData
  43. //    Purpose:        Handles the SetData Apple Event, extracting the direct
  44. //                    object (which says what to set) and the data (what to set
  45. //                    it to).
  46. // --------------------------------------------------------------------------
  47.      
  48. pascal OSErr    DoSetData(const AppleEvent    *theAppleEvent,
  49.                                 AppleEvent    *reply,
  50.                                 long        handlerRefCon)
  51. {
  52. #pragma unused (reply, handlerRefCon)
  53.     
  54.     AEDesc     directObj = {typeNull, NULL},
  55.             dataDesc = {typeNull, NULL};
  56.     OSErr      err;
  57.             
  58.         // pick up the direct object, which is the object whose data is to be set
  59.     err = AEGetParamDesc(theAppleEvent,  keyDirectObject,
  60.                                     typeWildCard, &directObj);
  61.     if (noErr != err) goto done;
  62.         
  63.         // now the data to set it to - typeWildCard means get as is
  64.         // e.g. this is the name of the font for text
  65.     err = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &dataDesc);
  66.     if (noErr != err) goto done;
  67.     
  68.         // missing any parameters?
  69.     err = GotRequiredParams(theAppleEvent);
  70.     if (noErr != err) goto done;
  71.     
  72.         // set the data
  73.     err = HandleSetData(&directObj, &dataDesc);
  74.  
  75. done:            
  76.     if (directObj.dataHandle)
  77.         AEDisposeDesc(&directObj);
  78.     if (dataDesc.dataHandle)
  79.         AEDisposeDesc(&dataDesc);
  80.  
  81.     return(err);
  82. }    // DoSetData
  83.  
  84.  
  85. // ---------------------------------------------------------------------------
  86. //        Name:             HandleSetData
  87. //        Purpose:        Resolves the object into a token (could be one of 
  88. //                        many) andthe sets the data of that object to dataDesc.
  89. // ---------------------------------------------------------------------------
  90.      
  91. OSErr HandleSetData(const AEDesc *theObj, AEDesc *dataDesc)
  92. {
  93.     TextToken       theTextToken;
  94.     Size            tokenSize;
  95.     AEDesc          objTokenDesc = {typeNull, NULL},
  96.                     itemDesc = {typeNull, NULL},
  97.                     ignoreResult = {typeNull, NULL};
  98.     long            index;
  99.     DescType        returnedType;
  100.     OSErr           err;
  101.  
  102.         //    Coerce theObj into a token which we can use - 
  103.         //         set the property or data for that token
  104.     if (typeObjectSpecifier == theObj->descriptorType)
  105.         err = AEResolve(theObj, kAEIDoMinimum, &objTokenDesc);
  106.     else    // Otherwise, just copy it
  107.         err = AEDuplicateDesc(theObj, &objTokenDesc);
  108.  
  109.     if (noErr != err) goto done;
  110.             
  111.     switch (objTokenDesc.descriptorType)
  112.     {
  113.         case typeMyWindowProp:
  114.             err = DoSetWindowProperty(&objTokenDesc, dataDesc);
  115.             break;
  116.         
  117.         case typeMyTextProp:
  118.             err = SetTextProperty(&objTokenDesc, dataDesc);
  119.             break;
  120.             
  121.         case typeMyText:
  122.             GetRawDataFromDescriptor(&objTokenDesc,  (Ptr)&theTextToken,
  123.                                             sizeof(theTextToken), &tokenSize);
  124.             
  125.                         // itemDesc is a null descriptor here
  126.             err = CreateAtTextToken(cText, dataDesc, &theTextToken,
  127.                                                     &itemDesc, &ignoreResult);
  128.             break;
  129.  
  130.         case typeAEList:                // If it's a list then do each item
  131.             err = AECountItems(&objTokenDesc, &index);
  132.             if (noErr != err) goto done;
  133.  
  134.             for (; index > 0; index--)
  135.             {
  136.                 err = AEGetNthDesc(&objTokenDesc, index, typeWildCard, &returnedType, &itemDesc);
  137.  
  138.                 if (noErr == err)        // Get property by calling this function again
  139.                     err = HandleSetData(&itemDesc, dataDesc);
  140.                 
  141.                 if (itemDesc.dataHandle)
  142.                     AEDisposeDesc(&itemDesc);
  143.             }
  144.             break;
  145.             
  146.         default:
  147.             err = errAEWrongDataType;
  148.     }
  149.  
  150. done:
  151.     if (objTokenDesc.dataHandle)    
  152.         AEDisposeDesc(&objTokenDesc);
  153.     if (itemDesc.dataHandle)    
  154.         AEDisposeDesc(&itemDesc);
  155.     if (ignoreResult.dataHandle)
  156.         AEDisposeDesc(&ignoreResult);
  157.  
  158.     return(err);
  159. } // HandleSetData
  160.  
  161.  
  162. OSErr    SetWindowSelectionProperty(WindowPtr theWindow, const AEDesc *dataDesc)
  163. {
  164.     AEDesc        textDesc = {typeNull, NULL},
  165.                 ignoreResult = {typeNull, NULL};
  166.     TextToken    aTextToken;
  167.     Size        actualSize;
  168.     short        ignore;
  169.     OSErr        err;
  170.         
  171.     // first check to see if we are dealing with a TEXT descriptor or
  172.     // an object specifier. Since AECoerceDesc will end up calling
  173.     // AEResolve, we don't want to call this if the user entered something
  174.     // like 'Set selection of window 1 to "some text '
  175.  
  176.     switch (dataDesc->descriptorType)
  177.     {
  178.         case typeChar:
  179.         case typeIntlText:
  180.         case typeStyledText:
  181.             err = GetWindowSelection(theWindow, &aTextToken, &ignore);
  182.             if (noErr != err) goto done;
  183.  
  184.                         // textDesc is a null descriptor here
  185.             err = CreateAtTextToken(cText, dataDesc, &aTextToken,
  186.                                                     &textDesc, &ignoreResult);
  187.             break;
  188.             
  189.         default:     // we are dealing with an object specifier
  190.             err = AECoerceDesc(dataDesc, typeMyText, &textDesc);
  191.             if (noErr != err) goto done;
  192.             
  193.             GetRawDataFromDescriptor(&textDesc, (Ptr)&aTextToken, sizeof(aTextToken),
  194.                                             &actualSize);
  195.                                             
  196.             SelectTextToken(&aTextToken);
  197.     }
  198.  
  199. done:
  200.     if (textDesc.dataHandle)
  201.         AEDisposeDesc(&textDesc);
  202.  
  203.     return(err);
  204. }
  205.  
  206.  
  207. // ------------------------------------------------------------------------
  208. //    Name:         SetWindowProperty
  209. //    Purpose:    Sets the window property specified in theWindowPropToken to
  210. //                be that supplied in dataDesc.
  211. // ------------------------------------------------------------------------
  212.      
  213. OSErr    DoSetWindowProperty(const AEDesc *theWPTokenDesc, const AEDesc *dataDesc)
  214. {
  215.     Str255          theNewName;
  216.     DPtr            theDocument;
  217.     Rect            thePosnRect;
  218.     Boolean         theBoolean;
  219.     GrafPtr         oldPort;
  220.     Point           thePosn;
  221.     THPrint         theTHPrint;
  222.     WindowPropToken theWindowPropToken;
  223.     TextToken        aTextToken;
  224.     AEDesc          aDesc = {typeNull, NULL},
  225.                     nullDesc = {typeNull, NULL},
  226.                     ignoreResult = {typeNull, NULL};
  227.     Size            tokenSize;
  228.     short           hOffset;
  229.     short           vOffset;
  230.     OSErr           err;
  231.  
  232.     GetPort(&oldPort);
  233.  
  234.     err = AECoerceDesc(theWPTokenDesc, typeMyWindowProp, &aDesc);
  235.     if (noErr != err) goto done;
  236.  
  237.     GetRawDataFromDescriptor(&aDesc, (Ptr)&theWindowPropToken,
  238.                                     sizeof(theWindowPropToken), &tokenSize);
  239.  
  240.     SetPort(theWindowPropToken.tokenWindowToken.tokenWindow);
  241.     
  242.     theDocument = DPtrFromWindowPtr(theWindowPropToken.tokenWindowToken.tokenWindow);
  243.     
  244.     switch (theWindowPropToken.tokenProperty)
  245.     {
  246.         case pName:
  247.             err = GetPStringFromDescriptor(dataDesc, theNewName);
  248.             if (noErr != err) goto done;
  249.  
  250.             if (theNewName[0] == 0) 
  251.                 err = errAEWrongDataType;
  252.             else
  253.             {
  254.                 SetWTitle(theWindowPropToken.tokenWindowToken.tokenWindow, theNewName);
  255.                 PStrCopy(theDocument->theFileName, theNewName); // Should we do this???
  256.                 theDocument->dirty = true;
  257.             }
  258.             break;
  259.             
  260.         case pText:
  261.         case pContents:
  262.                             // Get whole window as place to insert data
  263.             err = TextTokenFromWindowToken(&(theWindowPropToken.tokenWindowToken), &aTextToken);
  264.             if (noErr != err) goto done;
  265.  
  266.             err = CreateAtTextToken(cText, dataDesc, &aTextToken,
  267.                                                     &nullDesc, &ignoreResult);
  268.             break;
  269.             
  270.         case pBounds:
  271.             err = GetRectFromDescriptor(dataDesc, &thePosnRect);
  272.             // the rectangle is for the structure region, and is in global coordinates
  273.             // MoveWindow and SizeWindow apply to the content region, so we have to massage a little
  274.  
  275.             thePosnRect.top    += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.top -
  276.                                   (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.top;
  277.                                                         
  278.             thePosnRect.left   += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.left -
  279.                                   (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.left;
  280.                                                         
  281.             thePosnRect.bottom += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.bottom -
  282.                                   (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.bottom;
  283.                                                         
  284.             thePosnRect.right  += (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.right -
  285.                                   (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.right;
  286.             
  287.             if (EmptyRect(&thePosnRect)) 
  288.                 err = errAECorruptData;
  289.             else
  290.             {
  291.                 MoveWindow(theWindowPropToken.tokenWindowToken.tokenWindow,
  292.                                      thePosnRect.left,
  293.                                      thePosnRect.top,
  294.                                      false);
  295.                 SizeWindow(theWindowPropToken.tokenWindowToken.tokenWindow,
  296.                                      thePosnRect.right- thePosnRect.left,
  297.                                      thePosnRect.bottom-thePosnRect.top,
  298.                                      true);
  299.                 DoResizeWindow(theDocument);
  300.             }
  301.             break;
  302.             
  303.         case pPosition:
  304.             err = GetPointFromDescriptor(dataDesc, &thePosn);
  305.             // the point is for the structure region, and is in global coordinates
  306.             // MoveWindow applies to the content region, so we have to massage a little
  307.     
  308.             hOffset = (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.left -
  309.                       (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.left;
  310.                                 
  311.             vOffset = (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->contRgn).rgnBBox.top -
  312.                       (**((WindowPeek)theWindowPropToken.tokenWindowToken.tokenWindow)->strucRgn).rgnBBox.top;
  313.                                 
  314.                                 
  315.             thePosn.v  += vOffset;
  316.             thePosn.h  += hOffset;
  317.             
  318.             MoveWindow(theWindowPropToken.tokenWindowToken.tokenWindow,
  319.                                  thePosn.h,
  320.                                  thePosn.v,
  321.                                  false);
  322.                                  
  323.             DoResizeWindow(theDocument);
  324.             break;
  325.             
  326.         case pIsZoomed:
  327.             err = GetBooleanFromDescriptor(dataDesc, &theBoolean);
  328.             if (theBoolean)
  329.                 ZoomWindow(qd.thePort, inZoomOut, false);
  330.             else
  331.                 ZoomWindow(qd.thePort, inZoomIn, false);
  332.                                                      
  333.             DoResizeWindow(theDocument);
  334.             break;
  335.             
  336.         case pVisible:
  337.             err = GetBooleanFromDescriptor(dataDesc, &theBoolean);
  338.             if (theBoolean)
  339.                 ShowWindow(theWindowPropToken.tokenWindowToken.tokenWindow);
  340.             else
  341.                 HideWindow(theWindowPropToken.tokenWindowToken.tokenWindow);
  342.             break;
  343.             
  344.         case pPageSetup:
  345.                 err = GetTHPrintFromDescriptor(dataDesc, &theTHPrint);
  346.                     
  347.                 if (theTHPrint) 
  348.                 {
  349.                     if (theDocument->thePrintSetup) 
  350.                         DisposeHandle((Handle)theDocument->thePrintSetup);
  351.                         
  352.                     theDocument->thePrintSetup = theTHPrint;
  353.                     
  354.                     ResizePageSetupForDocument(theDocument);
  355.                 }
  356.             
  357.         case pSelection:
  358.             err = SetWindowSelectionProperty(theWindowPropToken.tokenWindowToken.tokenWindow, dataDesc);
  359.             break;
  360.     
  361.         default:    
  362.             err = errAEEventNotHandled;
  363.     }
  364.     
  365. done:
  366.     if (aDesc.dataHandle)    
  367.         AEDisposeDesc(&aDesc);
  368.     if (nullDesc.dataHandle)        // You'd hope not
  369.         AEDisposeDesc(&nullDesc);
  370.     if (ignoreResult.dataHandle)    
  371.         AEDisposeDesc(&ignoreResult);
  372.  
  373.     SetPort(oldPort);
  374.     
  375.     return(err);
  376. } // SetWindowProperty
  377.  
  378.  
  379.  
  380. OSErr    GetTHPrintFromDescriptor(const AEDesc *sourceDesc, THPrint *result)
  381. {
  382.     Size    ptSize;
  383.     AEDesc  resultDesc;
  384.     OSErr   err;
  385.     
  386.     *result = NULL;
  387.     
  388.     err = AECoerceDesc(sourceDesc, typeTPrint, &resultDesc);
  389.     if (noErr != err) goto done;
  390.     
  391.     *result = (THPrint)NewHandle(sizeof(TPrint));
  392.     
  393.     PrOpen();
  394.     PrintDefault(*result);
  395.     
  396.     HLock((Handle)*result);
  397.     GetRawDataFromDescriptor(&resultDesc, (Ptr)**result, sizeof(TPrint), &ptSize);
  398.     HUnlock((Handle)*result);
  399.     
  400.     if ((ptSize<sizeof(TPrint)) || (PrValidate(*result)))
  401.     {
  402.         err = errAECoercionFail;
  403.         DisposeHandle((Handle)*result);
  404.         *result = NULL;
  405.     }
  406.     
  407.     PrClose();
  408.  
  409. done:    
  410.     if (resultDesc.dataHandle) 
  411.         AEDisposeDesc(&resultDesc);
  412.         
  413.     return(err);
  414. } // GetTHPrintFromDescriptor
  415.  
  416.  
  417.  
  418. // ----------------------------------------------------------------------
  419. //    Name:         SetTextProperty
  420. //    Purpose:    Sets the text property specfied by theTextPropToken to
  421. //                that in dataDesc.
  422. // ----------------------------------------------------------------------
  423.      
  424. OSErr    SetTextProperty(const AEDesc *tokenDesc, const AEDesc *dataDesc)
  425. {
  426.     DPtr              theDoc;
  427.     Str255            name;
  428.     short             theSize;
  429.     Style             onStyle;
  430.     Style             offStyle;
  431.     TextPropToken     theTextPropToken;
  432.     AEDesc            newDesc = {typeNull, NULL},
  433.                     nullDesc = {typeNull, NULL},
  434.                     ignoreResult = {typeNull, NULL};
  435.     Size              tokenSize;
  436.     OSErr             err;
  437.     
  438.       err = AECoerceDesc(tokenDesc, typeMyTextProp, &newDesc);
  439.       if (noErr != err) goto done;
  440.  
  441.     GetRawDataFromDescriptor(&newDesc, (Ptr)&theTextPropToken,
  442.                                     sizeof(theTextPropToken), &tokenSize);
  443.         
  444.     theDoc = DPtrFromWindowPtr(theTextPropToken.tokenTextToken.tokenWindow);
  445.     theDoc->dirty = true;
  446.     
  447.     switch (theTextPropToken.tokenProperty)
  448.     {
  449.         case pText:
  450.         case pContents:
  451.             err = CreateAtTextToken(cText, dataDesc, &(theTextPropToken.tokenTextToken),
  452.                                                                 &nullDesc, &ignoreResult);
  453.             break;
  454.             
  455.         case pFont:
  456.             err = GetPStringFromDescriptor(dataDesc, name);
  457.             if (noErr != err) goto done;
  458.             err = SetFontOfTextToken(&theTextPropToken.tokenTextToken, name);
  459.             break;
  460.             
  461.         case pPointSize:    
  462.             err = GetIntegerFromDescriptor(dataDesc, &theSize);
  463.             if (noErr != err) goto done;
  464.             err = SetSizeOfTextToken(&theTextPropToken.tokenTextToken, theSize);
  465.             break;
  466.             
  467.         case pTextStyles:
  468.             onStyle  = 0;
  469.             offStyle = 0;
  470.             
  471.             err = GetTextStyles(dataDesc, &onStyle, &offStyle);
  472.             if (noErr != err) goto done;
  473.  
  474.             if (onStyle & offStyle != 0)
  475.                 err = errAEEventFailed;
  476.             else
  477.                 err = SetStyleOfTextToken(&theTextPropToken.tokenTextToken, onStyle, offStyle);
  478.             break;
  479.         
  480.         default:
  481.             err = errAEWrongDataType;
  482.     }
  483.  
  484. done:
  485.     if (newDesc.dataHandle)
  486.         AEDisposeDesc(&newDesc);
  487.             
  488.     return(err);
  489. } // SetTextProperty
  490.  
  491.     
  492. short ItemForNamedFont(Str255 theName)
  493. {
  494.     Str255  itemName;
  495.     short   limit;
  496.  
  497.     limit = CountMItems(myMenus[fontM]);
  498.     while (limit>0)
  499.     {
  500.         GetMenuItemText(myMenus[fontM],limit, itemName);
  501.         if (EqualString(theName, itemName,true,false)==0) 
  502.             return(limit);
  503.         else
  504.             limit--;
  505.     }
  506.     return(0);
  507. } // ItemForNamedFont
  508.  
  509.  
  510. // -----------------------------------------------------------------------
  511. //    Name:         SetFontOfTextToken
  512. //    Purpose:    Sets the font of the text specified by theToken to 
  513. //                the font in name.
  514. // -----------------------------------------------------------------------
  515.      
  516. OSErr    SetFontOfTextToken(TextToken* theToken, Str255 name)
  517. {
  518.     DPtr        docPtr;
  519.     TextToken    oldSelection;
  520.     short        theNumber,
  521.                 theItem;
  522.     TextStyle    newStyle;
  523.     Boolean        fCurrentSelection;
  524.     OSErr        err;
  525.  
  526.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  527.     
  528.     if (!docPtr) return(errAENoSuchObject);
  529.         
  530.                 // ignore theNumber result
  531.     err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &theNumber);
  532.     if (noErr != err) goto done;
  533.     
  534.     if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
  535.     {
  536.         fCurrentSelection = false;
  537.         err = SelectTextToken(theToken);    // Only set the selection if it's different
  538.         if (noErr != err) goto done;
  539.     }
  540.     else
  541.         fCurrentSelection = true;
  542.             
  543.     GetFNum(name, &theNumber);
  544.     
  545.     theItem = ItemForNamedFont(name); // returns 0 if failed - i.e. SystemFont
  546.     
  547.     if (gFontMItem)
  548.         CheckItem(myMenus[fontM], gFontMItem, false);
  549.     
  550.     gFontMItem = theItem;
  551.     CheckItem(myMenus[fontM], gFontMItem, true);
  552.     
  553.     docPtr->theFont = theNumber;
  554.         
  555.     newStyle.tsFont = theNumber;
  556.     TESetStyle(doFont, &newStyle, true, docPtr->theText); 
  557.     
  558.     AdjustScrollbars(docPtr, false);
  559.     DrawPageExtras(docPtr);
  560.     docPtr->dirty = true;
  561.     
  562.     if (! fCurrentSelection)
  563.         err = SelectTextToken(&oldSelection);
  564.  
  565. done:    
  566.     return(err);
  567. } // SetFontOfTextToken
  568.     
  569. // -----------------------------------------------------------------------
  570. //    Name:             SetSizeOfTextToken
  571. //    Purpose:        Sets the size of the text specified by theToken to 
  572. //                    the size in theSize.
  573. // -----------------------------------------------------------------------
  574.      
  575. OSErr    SetSizeOfTextToken(TextToken* theToken, short theSize)
  576. {
  577.     DPtr        docPtr;
  578.     TextToken    oldSelection;
  579.     TextStyle    newStyle;
  580.     short        ignore;
  581.     Boolean        fCurrentSelection;
  582.     OSErr        err;
  583.  
  584.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  585.     
  586.     if (!docPtr) return(errAENoSuchObject);
  587.         
  588.                 // Save the old selection
  589.     err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &ignore);
  590.     if (noErr != err) goto done;
  591.     
  592.     if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
  593.     {
  594.         fCurrentSelection = false;
  595.         err = SelectTextToken(theToken);
  596.         if (noErr != err) goto done;
  597.     }
  598.     else
  599.         fCurrentSelection = true;
  600.                             
  601.     docPtr->theSize = theSize;
  602.     
  603.     newStyle.tsSize = theSize;
  604.     TESetStyle(doSize, &newStyle, true, docPtr->theText); 
  605.     
  606.     AdjustScrollbars(docPtr, false);
  607.     DrawPageExtras(docPtr);
  608.     docPtr->dirty = true;
  609.     
  610.     if (! fCurrentSelection)    // If we reset the selection we may loose the
  611.         err = SelectTextToken(&oldSelection);    // Size or style just set
  612.  
  613. done:    
  614.     return(err);
  615. } // SetSizeOfTextToken
  616.     
  617. // ------------------------------------------------------------------------
  618. //    Name:             SetStyleOfTextToken
  619. //    Purpose:        Sets the style of the text specified by theToken to 
  620. //                    the style in theStyle.
  621. // ------------------------------------------------------------------------
  622.      
  623. OSErr    SetStyleOfTextToken(TextToken* theToken, Style onStyle, Style offStyle)
  624. {
  625.     DPtr        docPtr;
  626.     TextToken    oldSelection;
  627.     TextStyle    newStyle;
  628.     short        mode;
  629.     Boolean        wasContinuous;
  630.     short        ignore;
  631.     Boolean        fCurrentSelection;
  632.     OSErr        err;
  633.  
  634.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  635.     
  636.     if (!docPtr) return(errAENoSuchObject);
  637.         
  638.                 // Save the old selection
  639.     err = GetWindowSelection(theToken->tokenWindow, &oldSelection, &ignore);
  640.     if (noErr != err) goto done;
  641.     
  642.     if (memcmp(theToken, &oldSelection, sizeof(TextToken)))
  643.     {
  644.         fCurrentSelection = false;
  645.         err = SelectTextToken(theToken);
  646.         if (noErr != err) goto done;
  647.     }
  648.     else
  649.         fCurrentSelection = true;
  650.                             
  651.     docPtr->theStyle = onStyle;
  652.     
  653.         // Check to see if off styles are on for whole selection
  654.     mode = doFace;
  655.     
  656.     wasContinuous = TEContinuousStyle(&mode, &newStyle, docPtr->theText);
  657.     if ((newStyle.tsFace & offStyle) != offStyle) // not off styles are on for all
  658.     {
  659.             // switch on across board so that toggle off will clear all
  660.         newStyle.tsFace  = offStyle - (newStyle.tsFace & offStyle);
  661.         TESetStyle(doFace+doToggle, &newStyle, false, docPtr->theText); 
  662.     }
  663.         
  664.     newStyle.tsFace  = offStyle;
  665.     TESetStyle(doFace+doToggle, &newStyle,(onStyle==0), docPtr->theText); // toggle all to off
  666.     
  667.     mode = doFace;
  668.     if (onStyle)
  669.     {
  670.         wasContinuous = TEContinuousStyle(&mode, &newStyle, docPtr->theText);
  671.         if ((newStyle.tsFace & onStyle) != onStyle) // are they on for only a few chars
  672.         { 
  673.                 // Need to make all chars have these characteristics
  674.             newStyle.tsFace = onStyle - (newStyle.tsFace & onStyle); // take out those continuous
  675.             TESetStyle(doFace+doToggle, &newStyle, true, docPtr->theText);
  676.         }
  677.         else
  678.             TESetStyle(0, &newStyle, true, docPtr->theText); // Just Draw it, no changes
  679.     }
  680.         
  681.     AdjustScrollbars(docPtr, false);
  682.     DrawPageExtras(docPtr);
  683.     docPtr->dirty = true;
  684.     
  685.     if (! fCurrentSelection)
  686.         err = SelectTextToken(&oldSelection);
  687.  
  688. done:    
  689.     return(err);
  690. } // SetStyleOfTextToken
  691.  
  692.     
  693. OSErr    GetTextStyles(const AEDesc *dataDesc, Style *onStyles, Style *offStyles)
  694. {
  695.     OSErr      myErr;
  696.     OSErr      ignoreErr;
  697.     AEDescList textSDesc;
  698.     AEDescList onDesc;
  699.     AEDescList offDesc;
  700.     Boolean    hadPlain;
  701.         
  702.   textSDesc.dataHandle = nil;
  703.   onDesc.dataHandle    = nil;
  704.   offDesc.dataHandle   = nil;
  705.     
  706.     *onStyles  = 0;
  707.     *offStyles = 0;
  708.     
  709.   myErr = AECoerceDesc(dataDesc, typeAERecord, &textSDesc);
  710.     
  711.     if (myErr==noErr)
  712.       myErr = AEGetKeyDesc(&textSDesc, keyAEOnStyles, typeAEList, &onDesc);
  713.     
  714.     if (myErr==noErr)
  715.       myErr = AEGetKeyDesc(&textSDesc, keyAEOffStyles, typeAEList, &offDesc);
  716.     
  717.     if (myErr==noErr)
  718.         myErr = MakeStyleFromAEList(&onDesc,  onStyles, &hadPlain);
  719.     
  720.     if (hadPlain)
  721.         *offStyles = bold+italic+underline+outline+shadow+condense+extend;
  722.     else
  723.         {
  724.             if (myErr==noErr)
  725.                 myErr = MakeStyleFromAEList(&offDesc, offStyles, &hadPlain);
  726.             
  727.             if (hadPlain)
  728.                 myErr = errAEEventFailed;
  729.         }
  730.         
  731.     if (textSDesc.dataHandle)
  732.         ignoreErr = AEDisposeDesc(&textSDesc);
  733.         
  734.     if (onDesc.dataHandle)
  735.         ignoreErr = AEDisposeDesc(&onDesc);
  736.         
  737.     if (offDesc.dataHandle)
  738.         ignoreErr = AEDisposeDesc(&offDesc);
  739.     
  740.     return(myErr);
  741. } // GetTextStyles
  742.  
  743. // -----------------------------------------------------------------------
  744. //    Name:         AddDescStyleItem
  745. //    Purpose:    Adds the kAEXXXX style to theStyle.
  746. // -----------------------------------------------------------------------
  747.      
  748. void    AddDescStyleItem(DescType theDesc, Style *theStyle)
  749. {
  750.     if (theDesc == kAEBold)
  751.         *theStyle = *theStyle+bold;
  752.     else
  753.     if (theDesc == kAEItalic)
  754.         *theStyle = *theStyle+italic;
  755.     else
  756.     if (theDesc == kAEUnderline)
  757.         *theStyle = *theStyle+underline;
  758.     else
  759.     if (theDesc == kAEOutline)
  760.         *theStyle = *theStyle+outline;
  761.     else
  762.     if (theDesc == kAEShadow)
  763.         *theStyle = *theStyle+shadow;
  764.     else
  765.     if (theDesc == kAECondensed)
  766.         *theStyle = *theStyle+condense;
  767.     else
  768.     if (theDesc == kAEExpanded)
  769.         *theStyle = *theStyle+extend;
  770.     else
  771.     if (theDesc == kAEPlain)
  772.         *theStyle = 0;
  773. } // AddDescStyleItem
  774.     
  775. OSErr    MakeStyleFromAEList(const AEDescList *styleList, Style *theStyle, Boolean *hadPlain)
  776. {
  777.     OSErr     myErr;
  778.     DescType  styleDesc;
  779.     long      itemsInList;
  780.     long      actSize;
  781.     AEKeyword keywd;
  782.     DescType  typeCode;
  783.         
  784.     *hadPlain = false;
  785.     *theStyle = 0;
  786.     
  787.   myErr = AECountItems(styleList, &itemsInList);
  788.     while (itemsInList>0)
  789.       if (myErr==noErr)
  790.             {
  791.                 myErr  = AEGetNthPtr(styleList,
  792.                                                          itemsInList,
  793.                                                          typeEnumerated,
  794.                                                          &keywd,
  795.                                                          &typeCode,
  796.                                                          (Ptr)&styleDesc,
  797.                                                          sizeof(styleDesc),
  798.                                                          &actSize);
  799.                 
  800.                 AddDescStyleItem(styleDesc, theStyle);
  801.                 
  802.                 if (styleDesc == kAEPlain) 
  803.                   {
  804.                         itemsInList = 0;
  805.                         *hadPlain    = true;
  806.                     }
  807.                 else
  808.                   itemsInList--;
  809.             }
  810.             
  811.     return(myErr);
  812. } // MakeStyleFromAEList
  813.